home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xsok-1.000 / xsok-1 / xsok-1.01 / src / mousemove.c < prev    next >
C/C++ Source or Header  |  1994-11-24  |  3KB  |  134 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    Xsok version 1.00 -- module mousemove.c                     */
  5. /*                                         */
  6. /*    Computes paths to squares in the distance.                 */
  7. /*    Written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de)             */
  8. /*    November-1994                                 */
  9. /*    see COPYRIGHT.xsok for Copyright details                 */
  10. /*                                         */
  11. /*                                         */
  12. /*****************************************************************************/
  13. #ifndef _POSIX_SOURCE
  14. #define _POSIX_SOURCE
  15. #endif
  16. #include "xsok.h"
  17.  
  18. static int before_move;
  19.  
  20. void cmd_MouseUndo(void) {
  21.     if (lastcmd != &cmd_MouseMove && lastcmd != &cmd_MousePush && lastcmd
  22.     != cmd_PlayMacro) {
  23.     cmd_UndoMove();    /* normal undo */
  24.     return;
  25.     }
  26.     jumpto_movenr(before_move);
  27.     cmd_ShowScore();
  28. }
  29.     
  30. #define RBSIZE      1024    /* only powers of 2 will work */
  31. #ifndef sgn
  32. #define sgn(x)        ((x) < 0 ? -1 : 1)
  33. #endif
  34.  
  35. #define STEP(dx,dy) if ( \
  36.   (map[y+(dy)][x+(dx)]->mask & 1) && \
  37.    map[y+(dy)][x+(dx)]->enter == 0xf && \
  38.    map[y+(dy)][x+(dx)]->leave == 0xf && \
  39.    !obj[y+(dy)][x+(dx)] && \
  40.    dist[y+(dy)][x+(dx)] > d) { \
  41.     dist[remy[wr] = y+(dy)][remx[wr]= x+(dx)] = d; \
  42.     if ((wr = (wr + 1) & (RBSIZE-1)) == rd) break; }
  43.  
  44. void cmd_MouseMove(void) {
  45.     int xx = mouse_x, yy = mouse_y;
  46.     unsigned dist[MAXROW][MAXCOL];
  47.     int rd = 0, wr = 1, remx[RBSIZE], remy[RBSIZE];
  48.     struct objects *ip = obj[game.y][game.x];
  49.  
  50.     before_move = game.n_moves;
  51.     /* case 1: a distance 1 click will move or push */
  52.     if (xx == game.x && yy == game.y)
  53.     return;    /* shortcut! */
  54.  
  55.     if (abs(xx - game.x) + abs(yy - game.y) == 1) {
  56.     if (xx - game.x)
  57.         if (xx > game.x)
  58.         playermove(3);
  59.         else
  60.         playermove(1);
  61.     else
  62.         if (yy > game.y)
  63.         playermove(2);
  64.         else
  65.         playermove(0);
  66.     return;
  67.     }
  68.     /* for greater distance, only use free space. Therefore, we must */
  69.     /* temporary remove the player ;-) */
  70.     if (!(map[yy][xx]->mask & 1))
  71.     goto nopath;
  72.     obj[game.y][game.x] = NULL;
  73.     memset(dist, 0xff, sizeof(dist));
  74.     remx[0] = xx;
  75.     remy[0] = yy;
  76.     dist[yy][xx] = 0;
  77.     while (rd != wr) {
  78.     int x, y, d;
  79.     x = remx[rd];
  80.     y = remy[rd];
  81.     rd = (rd+1) & (RBSIZE-1);
  82.     d = 1 + dist[y][x];
  83.     STEP(1,0);
  84.     STEP(0,1);
  85.     STEP(-1,0);
  86.     STEP(0,-1);
  87.     if (dist[game.y][game.x] < 30000)
  88.         goto have_path;
  89.     }
  90.     /* no path is found */
  91.  nopath:
  92.     obj[game.y][game.x] = ip;
  93.     show_message(TXT_MOVENOTPOSSIBLE);
  94.     return;
  95.  
  96. have_path:
  97.     obj[game.y][game.x] = ip;
  98.     while (game.y != yy || game.x != xx) {
  99.     unsigned length;
  100.     int omove;
  101.     length = dist[game.y][game.x] - 1;
  102.     omove = game.n_moves;
  103.          if (dist[game.y-1][game.x] == length) playermove(0);
  104.     else if (dist[game.y][game.x-1] == length) playermove(1);
  105.     else if (dist[game.y+1][game.x] == length) playermove(2);
  106.     else if (dist[game.y][game.x+1] == length) playermove(3);
  107.     if (dist[game.y][game.x] > length)
  108.         break;    /* else may cause cycling (with teleporters) */
  109.     if (game.n_moves != omove + 1)
  110.         break;    /* precomputed move not possible any more */
  111.     }
  112. }
  113.  
  114. void cmd_MousePush(void) {
  115.     int dx, dy, i, dir;
  116.  
  117.     before_move = game.n_moves;
  118.     dx = mouse_x - game.x;
  119.     dy = mouse_y - game.y;
  120.     if (dx && dy) {
  121.     cmd_MouseMove();
  122.     return;        /* either horizontally or vertically */
  123.     }
  124.     if (dx) {
  125.     i = abs(dx);
  126.     dir = 2 + sgn(dx);
  127.     } else {
  128.     i = abs(dy);
  129.     dir = 1 + sgn(dy);
  130.     }
  131.     while (i--)
  132.     playermove(dir);
  133. }
  134.